package com.ruoyi.web.controller.system;

import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.SysVip;
import com.ruoyi.system.domain.WxCheckoutBody;
import com.ruoyi.system.domain.WxRecords;
import com.ruoyi.system.domain.WxUser;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysVipService;
import com.ruoyi.system.service.IWxRecordsService;
import com.ruoyi.system.service.IWxUserService;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.ResponseEntity;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 微信信息Controller
 * 
 * @author ruoyi
 * @date 2025-08-06
 */
@RestController
@RequestMapping("/api/wxuser")
public class WechatController extends BaseController
{
    @Autowired
    private IWxUserService wxUserService;

    @Autowired
    private IWxRecordsService wxRecordsService;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private ISysVipService vipService;

    /**
     * 获取游戏记录
     */
    @PostMapping("/list")
    public AjaxResult getList(@RequestBody WxRecords record) {
        List<WxRecords> list = wxRecordsService.selectWxRecordsList(record);
        return AjaxResult.success(list);
    }

    /**
     * 查看当前微信用户是否有权限管理商家信息
     */
    @PostMapping("/permission")
    public AjaxResult getPermission(@RequestBody WxRecords record){
        SysDept dept = deptService.selectDeptByWxId(record.getWxId());
        return AjaxResult.success(dept == null ? false: true);
    }

    /**
     * 获取商家当前游戏记录
     */
    @PostMapping("/records")
    public AjaxResult getListByDept(@RequestBody WxRecords record){
        SysDept dept = deptService.selectDeptByWxId(record.getWxId());
        WxRecords temp = new WxRecords();
        temp.setDeptId(dept.getDeptId());
        temp.setStatus(record.getStatus());
        temp.setStartTime(new Date());
        List<WxRecords> list = wxRecordsService.selectWxRecordsList(temp);
        return AjaxResult.success(list);
    }

    /**
     * 获取微信openid
     */
    @PostMapping("/getOpenid")
    public AjaxResult getOpenid(@RequestBody Map<String, String> params) {
        String code = params.get("code");
        String appid = "wx076a3d28504e9275";
        String secret = "a97c07f9abb1f5cbfab2f94a740d0be9";
        try {
            String url = String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
                    appid, secret, code);

            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                ObjectMapper objectMapper = new ObjectMapper();
                Map<String, Object> jsonMap = objectMapper.readValue(response.getBody(), Map.class);

                // 检查微信API返回错误
                if (jsonMap.containsKey("errcode")) {
                    int errcode = (Integer) jsonMap.get("errcode");
                    String errmsg = (String) jsonMap.get("errmsg");
                    throw new RuntimeException("微信API错误: " + errcode + " - " + errmsg);
                }

                String openid = (String) jsonMap.get("openid");
                if (openid == null || openid.isEmpty()) {
                    throw new RuntimeException("获取openid失败");
                }

                return new AjaxResult(200, "获取成功", openid);
            } else {
                throw new RuntimeException("网络请求失败: " + response.getStatusCode());
            }
        } catch (Exception e) {
            throw new RuntimeException("获取openid异常: " + e.getMessage(), e);
        }
        //String openid = "sldkfjsldkjhgasldgw43634"; //开发环境模拟一个假的openid
        //return new AjaxResult(200, "获取成功", openid);
    }

    /**
     * 保存微信信息  微信用户首次使用时，保存用户信息
     */
    @PostMapping("/save")
    public AjaxResult saveUser(@RequestBody WxUser user) {
        WxUser re = wxUserService.selectWxUserByOpenId(user.getOpenid());
        if (re != null) {
            //已经存在，则update
            return AjaxResult.success(wxUserService.updateWxUserByOpenid(user));
        } else {
            //第一次使用，则insert
            return AjaxResult.success(wxUserService.insertWxUser(user));
        }
    }

    /**
     * 根据openid获取wxUser
     */
    @PostMapping("/getUser")
    public AjaxResult getUser(@RequestBody WxUser user) {
        return  AjaxResult.success(wxUserService.selectWxUserByOpenId(user.getOpenid()));
    }


    /**
     * 开始游戏
     */
    @PostMapping("/start")
    public AjaxResult startGame(@RequestBody WxRecords record) {
        record.setStartTime(new Date());
        return AjaxResult.success(wxRecordsService.startGame(record));
    }

    /**
     * 结束游戏
     */
    @PostMapping("/end")
    public AjaxResult endGame(@RequestBody WxRecords record) {
        record.setEndTime(new Date());//设置结束游戏时间
        //计算金额
        SysDept dept = deptService.selectDeptById(record.getDeptId());
        String type = dept.getOfferType();
        switch (type) {
            case "1":
                //每天最多收4个小时的价钱
                //单价
                double price = 0;
                if(record.getGameType().equals("1")){
                    price = dept.getPs();
                }else if(record.getGameType().equals("2")){
                    price = dept.getSwitchs();
                }else{
                    price = dept.getBoard();
                }
                double top = price * 4;//当天付款上限
                double todayAmount = getTodayAmount(record);//当天已游玩金额
                if(todayAmount >= top){
                    record.setAmount((double) 0);//如果当天游戏已超过最高付款金额，则后续免费
                }else{
                    WxRecords tempRecord = wxRecordsService.getActiveRecord(record);
                    int amountMinutes = getMinutes(tempRecord.getStartTime(), record.getEndTime());//本次游玩分钟数

                    int minTime = dept.getMinDuration();//最小计时单位（分钟）
                    int timeCount = 0;
                    //分钟数整合，是舍还是入
                    if(dept.getChargeType().equals("0")){
                        timeCount = amountMinutes / minTime;
                    }else{
                        timeCount = amountMinutes % minTime == 0 ? amountMinutes / minTime : (amountMinutes / minTime) + 1;
                    }
                    price = price * minTime / 60;//按最小时间单位重新定义单价
                    double currentAmount = timeCount * price; //本次正常需要付的钱数

                    if(currentAmount + todayAmount >= top){
                        //如果本次需付款+当天应付或已付总额>上限，则只算上限-当天
                        record.setAmount(top - todayAmount);
                    }else{
                        //如果本次需付款+当天应付或已付总额<上限，则正常算本次
                        record.setAmount(currentAmount);
                    }
                }
                break;
            default:
                //默认计费模式，即type为0的情况，无优惠
                //单价
                price = 0;
                String a = record.getGameType();
                if(record.getGameType().equals("1")){
                    price = dept.getPs();
                }else if(record.getGameType().equals("2")){
                    price = dept.getSwitchs();
                }else{
                    price = dept.getBoard();
                }
                int minTime = dept.getMinDuration();//最小计时单位（分钟）
                int timeCount = 0;
                WxRecords tempRecord = wxRecordsService.getActiveRecord(record);
                int currentMinutes = getMinutes(tempRecord.getStartTime(), record.getEndTime());//本次游玩分钟数
                //分钟数整合，是舍还是入
                if(dept.getChargeType().equals("0")){
                    timeCount = currentMinutes / minTime;
                }else{
                    timeCount = currentMinutes % minTime == 0 ? currentMinutes / minTime : (currentMinutes / minTime) + 1;
                }
                price = price * minTime / 60;//按最小时间单位重新定义单价
                record.setAmount(timeCount * price);
                break;
        }
        int b = wxRecordsService.endGame(record);
        return AjaxResult.success(b);
    }

    /**
     * 单个玩家结账
     */
    @PostMapping("/checkoutOne")
    public AjaxResult checkout(@RequestBody WxRecords record) {
        return AjaxResult.success(wxRecordsService.checkoutOne(record));
    }

    /**
     * 查看游戏状态
     */
    @GetMapping("/duration")
    public AjaxResult duration(WxRecords wxRecords) {
        WxRecords record = wxRecordsService.getActiveRecord(wxRecords);
        return new AjaxResult(200, "获取成功", getMinutes(record.getStartTime(),new Date()));
    }

    /**
     * 查看是否有正在游玩的记录
     */
    @GetMapping("/status")
    public AjaxResult checkStatus(WxRecords wxRecords) {
        return AjaxResult.success(wxRecordsService.getActiveRecord(wxRecords) != null);
    }

    /**
     * 获取vip列表
     */
    @PostMapping("/vipList")
    public AjaxResult getVipList(@RequestBody SysVip temp) {
        SysDept dept = deptService.selectDeptByWxId(temp.getName());//拿name字段存的wxId
        SysVip vip = new SysVip();
        vip.setDeptId(dept.getDeptId());
        if(temp.getPhone() != null){
            vip.setPhone(temp.getPhone());
        }
        return AjaxResult.success(vipService.selectSysVipList(vip));
    }

    /**
     * 结账
     */
    @PostMapping("/checkoutVipMerge")
    public AjaxResult checkoutVipOrMerge(@RequestBody WxCheckoutBody body) {
        if(body.getVipId() == 0){
            //只改记录，不扣会员
            return toAjax(wxRecordsService.checkoutWhitoutVip(body));
        }else{
            //既改会员余额，也改游戏记录
            return toAjax(wxRecordsService.checkout(body));
        }
    }

    /**
     * 计算当天已累计的钱数
     */
    public double getTodayAmount(WxRecords record) {
        WxRecords temp = new WxRecords();
        temp.setWxId(record.getWxId());
        temp.setDeptId(record.getDeptId());
        temp.setStartTime(new Date());
        temp.setStatus("1");

        List<WxRecords> list1 = wxRecordsService.selectWxRecordsList(temp);

        //循环计算每条记录，开始时间和结束时间的分钟差，累加到minutes中
        double amount = (double) 0;

        for (WxRecords r : list1) {
            amount += r.getAmount();
        }

        temp.setStatus("2");
        List<WxRecords> list2 = wxRecordsService.selectWxRecordsList(temp);

        for (WxRecords r : list2) {
            amount += r.getAmount();
        }

        return amount;
    }

    /**
     * 计算当天已游玩分钟数
     */
    public int getTodayMinutes(WxRecords record) {
        WxRecords temp = new WxRecords();
        temp.setWxId(record.getWxId());
        temp.setDeptId(record.getDeptId());
        temp.setStartTime(new Date());
        temp.setStatus("1");

        List<WxRecords> list1 = wxRecordsService.selectWxRecordsList(temp);

        //循环计算每条记录，开始时间和结束时间的分钟差，累加到minutes中
        int minutes = 0;

        for (WxRecords r : list1) {
            Date start = r.getStartTime();
            Date end = r.getEndTime();
            minutes += getMinutes(start, end);
        }

        temp.setStatus("2");
        List<WxRecords> list2 = wxRecordsService.selectWxRecordsList(temp);

        for (WxRecords r : list2) {
            Date start = r.getStartTime();
            Date end = r.getEndTime();
            minutes += getMinutes(start, end);
        }

        return minutes;
    }

    /**
     * 分钟数做差
     */
    public int getMinutes(Date start, Date end){
        // 保护性判断
        if (start != null && end != null) {
            long diffMillis = end.getTime() - start.getTime();
            return (int) (diffMillis / (60 * 1000)); // 转为分钟
        }else{
            return 0;
        }
    }

}
